package asteroids.statement;

import asteroids.*;
import asteroids.expression.*;
import asteroids.model.programs.parsing.ProgramFactory.ForeachType;
import asteroids.model.programs.*;
import asteroids.expression.*;

import java.util.*;

public class ForEachStatement extends Statement {

	private List list;
	private boolean initialized = false;
	private World world;
	private Statement statement;
	private String variableName;

	private ForeachType kind;

	public ForEachStatement(ForeachType kind, String newVariableName,
			Statement s) {
		this.kind = kind;

		if (s == null) {
			this.statement = new SkipStatement();
		} else {
			this.statement = s;
		}
		if (newVariableName == null) {
			this.variableName = "";
		} else {
			this.variableName = newVariableName;
		}
	}

	public World getWorld() {
		return this.world;
	}

	private void setList(List list) {
		this.list = list;
	}

	public List getList() {
		return this.list;
	}

	public boolean isInitialized() {
		return this.initialized;
	}

	public ForeachType getKind() {
		return this.kind;
	}

	@Override
	public void execute(Program program) {
		if (!isInitialized()) {
			initialize(program);
		} else
			execute2(program);
	}

	private ArrayList<FlyingObject> MakeAnyList(FlyingObject obj) {
		int i = 0;
		World world = obj.getWorld();
		ArrayList<FlyingObject> result = new ArrayList<FlyingObject>();
		if (world != null) {

			while (i < world.getShips().size()) {
				result.add(world.getShips().get(i));
				i++;
			}
			i = 0;
			while (i < world.getAsteroids().size()) {
				result.add(world.getAsteroids().get(i));
				i++;
			}
			i = 0;
			while (i < world.getBullets().size()) {
				result.add(world.getBullets().get(i));
				i++;
			}
		}
		return result;
	}

	private void initialize(Program program) {
		FlyingObject obj = program.getOwner();
		if (obj != null) {
			if (obj.getWorld() != null) {
				this.world = obj.getWorld();
				if (getKind() == ForeachType.SHIP)
					setList(getWorld().getShips());
				else if (getKind() == ForeachType.ASTEROID)
					setList(getWorld().getAsteroids());
				else if (getKind() == ForeachType.BULLET)
					setList(getWorld().getBullets());
				else if (getKind() == ForeachType.ANY) {
					setList(MakeAnyList(obj));
				}

			}
		}
		this.stateNumber = 0;
		this.initialized = true;
		this.execute2(program);
	}

	private void execute2(Program program) {
		while (!this.isFinished()) {

			if (!(this.getStateNumber() < getSize())) {
				this.finished = true;

			} else if (statement.isFinished()) {
				statement.loop();
				incrementStateNumber();

			} else {
				// if(program.getGlobals().containsKey(variableName)){
				EntityExpression exp = new EntityExpression(
						(FlyingObject) list.get(getStateNumber()));
				program.setGlobals(variableName, exp);
				// }
				statement.execute(program);
			}
		}
	}

	@Override
	public int getSize() {
		return list.size();
	}

	@Override
	public void loop() {
		this.finished = false;
		this.stateNumber = 0;
		this.initialized = false;

	}

}
